<?php
/**
 * Класс реализующий виджет меню разделов
 * 
 * @package Phorm.CMS
 * @name /Phorm/Widget/Categories/Menu.php
 * @copyright phorm.ru
 * @since 10.12.2010
 * @author vladimir@kachalov.net
 */

class Phorm_Widget_Categories_Menu extends Phorm_Widget implements Phorm_Widget_Interface {

	/**
	 * Объект View
	 * @var Zend_View
	 */
	private $_view;
	
	/**
	 * Дерево разделов в виде Zend_Navigation
	 * @var Zend_Navigation
	 */
	private $_categories;
	
	/**
	 * Возвращает данные виджета, для передачи в шаблон
	 *
	 * @return array
	 */
	
	public function getData() {
		
		// Инициализируем объект Zend_View (используем чистый Zend_View)
		$this->_view = new Zend_View();
		$this->_view -> setBasePath(APPLICATION_PATH . '/templates/' . $this->_params['module']);
		
		// Создаем из дерева разделов объект меню
		$this->_categories = new Zend_Navigation($this->getCategoriesTree());
		
		// Вычленяем часть дерева, если опциями заданы начальные вершины + определяем активную ветку
		$this->_categories = $this->cropCategoriesTree()->setActiveBranch();
		
		$CategoriesMenu = $this->_categories;
		
		switch ($this->_options["type"]) {
			
			case "breadcrumbs":
				$menu = $this->getBreadcrumbs();
				break;
				
			case "childs":
				$menu = $this->getChilds();
				break;
				
			case "ajar":
				$menu = $this->getAjar();
				break;
				
			case "branch":
				$menu = $this->getBranch();
				break;
				
			case "brothers":
				$menu = $this->getBrothers();
				break;
				
			case "parent":

				$menu = $this->getParents();
				break;
				
			default:
				$menu = $this->getFull();
				break;
			
		}

		// Пытаемся отрендерить меню с итераторами
			
		$out = array(); 
		
		try {
			
			if(isset($this->_options['partial'])) {
				$menu->setPartial(array($this->_options['partial'] . '.partial.php', $this->_params['module']));	
			}
			$out['menu'] = $menu->render();
			
		} catch (Exception $e) {
			
			$menu->setPartial(null);
			$out['menu'] = $menu->render();
			
		}

			
		// Получаем заголовки для меню
			
		if($CategoriesMenu->key()) {
			$out['title'] = $CategoriesMenu->current()->getLabel();
			$out['name'] = $CategoriesMenu->current()->get('name');
		}
			
		return $out;
		
	}
	
	
	/**
	 * Хлебные крошки
	 *
	 * @return Zend_View_Helper_Navigation_Breadcrumbs
	 */
	
	private function getBreadcrumbs() {
		
		$menu = $this->_view->navigation()->breadcrumbs($this->_categories)->setSeparator(" / ");

		if(isset($this->_options['showindex']) && $this->_options['showindex']=='no') {
			$menu->setMinDepth(1)->setMaxDepth(null);
		} else {
			$menu->setMinDepth(null)->setMaxDepth(null);
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Прямые потомки
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getChilds() {
		
		if(empty($this->_options['categories']) && $this->_options['categories']!='null') {
					
			$current = $this->_categories->findBy('active',true);
			$menu = $this->_view->navigation()->menu($current);
			$menu -> setMaxDepth(0);
					
		} else {
					
			$menu = $this->_view->navigation()->menu($this->_categories);
			$menu->setMinDepth(1)->setMaxDepth(1);
					
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Приоткрытое дерево
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getAjar() {
		
		return $this->_view->navigation()->menu($this->_categories);
		
		$current = $this->_categories->findBy('active',true);
				
		$menu = $this->_view->navigation()->menu($current);
				
		if(isset($this->_options['showindex']) && $this->_options['showindex']=='no') {
			$menu->setMinDepth(1)->setMaxDepth(null);
		} else {
			$menu->setMinDepth(null)->setMaxDepth(null);
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Активная ветка
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getBranch() {
		
		$menu = $this->_view->navigation()->menu($this->_categories);
				
		$menu -> setOnlyActiveBranch(true);
				
		if(isset($this->_options['showindex']) && $this->_options['showindex']=='no') {
			$menu->setMinDepth(1)->setMaxDepth(null);
		} else {
			$menu->setMinDepth(null)->setMaxDepth(null);
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Братья
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getBrothers() {
		
		$current = $this->_categories->findBy('active',true);
				
		$menu = $this->_view->navigation()->menu($current->getParent());
					  
		$menu->setMinDepth(null)->setMaxDepth(0);
		
		return $menu;
		
	}
	
	
	/**
	 * Родители
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getParents() {
		
		$menu = $this->_view->navigation()->menu($this->_categories);
				
		if(isset($this->_options['showindex']) && $this->_options['showindex']=='no') {
			$menu->setMinDepth(1)->setMaxDepth(1);
		} else {
			$menu->setMinDepth(null)->setMaxDepth(1);
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Полностью раскрытое дерево
	 *
	 * @return Zend_View_Helper_Navigation_Menu
	 */
	
	private function getFull() {
		
		$menu = $this->_view->navigation()->menu($this->_categories);
				
		if(isset($this->_options['showindex']) && $this->_options['showindex']=='no') {
			$menu->setMinDepth(1)->setMaxDepth(null);
		} else {
			$menu->setMinDepth(null)->setMaxDepth(null);
		}
		
		return $menu;
		
	}
	
	
	/**
	 * Возвращает дерево видимых в системе разделов
	 *
	 * @return array
	 * @todo Заменить eval на рекурсию
	 */
	
	private function getCategoriesTree() {
		
		$cache = $this->getCache('categories');
		
		// Определяем наличие дерева в кэше
		
		if($cache->test('CategoriesVisibleTree')) {
			
			$CategoriesTree = $cache->load('CategoriesVisibleTree');
			
		} else {
			
			$Categories = new Phorm_Categories();
			
			// Делаем из плоского дерева иерархическое дерево
			
			foreach ($Categories->getVisibleList() as $data) {
				
				$fullpath = explode('/',$data['fullpath']);
				unset($fullpath[count($fullpath)-1]);
				
				$array = array_merge(
							array(
								"id" => $data["categoryid"],
								"label" => $data["menuname"],
								"name" => $data["categoryname"],
								"uri" => $data["fullpath"],
								"order" => $data["cleft"],
								"pages" => array()
							),$data);
							
				eval('$CategoriesTree["'.implode('"]["pages"]["',$fullpath).'"] = $array;');
				
			}
			
			$cache->save($CategoriesTree,'CategoriesVisibleTree');
			
		}
		
		return $CategoriesTree;
		
	}
	
	
	/**
	 * Вырезает кусок дерева на основе заданных вершин
	 *
	 * @return Zend_Navigation
	 */
	
	private function cropCategoriesTree() {
		
		if(is_array($this->_options['categories']) && !empty($this->_options['categories'])) {
			
			$iterator = new RecursiveIteratorIterator($this->_categories,RecursiveIteratorIterator::SELF_FIRST);
			
			$found = array();
			
			foreach ($iterator as $page) {
				if (in_array($page->get('id'),$this->_options['categories'])) {
					$found[] = $page;
				}
			}
			
			$this->_categories = new Zend_Navigation($found);
			
		}
		
		return $this;
		
	}
	
	
	/**
	 * Устанавливает активную ветку на основе текущего раздела
	 *
	 * @return Phorm_Widget_Categories_Menu
	 */
	
	private function setActiveBranch() {
		
		if(isset($this->_params['categoryinfo']['categoryid']) && $current = $this->_categories->findBy('id',$this->_params['categoryinfo']['categoryid'])) {
			
			$current->set('active',true);
			
			while($current = $this->_categories->findBy('id',$current->get('cparent'))) {
				$current->set('active',true);
			}
		
		}
		
		return $this->_categories;
		
	}
	
}
